	
	//Constants
	var PREFIX_CHAT_CONTENT_ID = 'chatContent_';
	var PREFIX_CHAT_CONTENT_SCROLLBAR_ID = 'scrollbarChatDialog_';
	var PREFIX_CHAT_TEXT_BOX_MESSAGE_ID = 'txtMsg_';
	var PREFIX_CHAT_DIALOG_ID = 'chatDialog_';
	var PREFIX_CHAT_CONTACT_ROW_ID = 'contact_';
	var DUMMY_CLASS_IAM_TYPING = "dummyClassIHaveJustSentMessage"; 
	var REFRESHING_CHATTING_PERIOD = 2;//second
	var REFRESHING_CHATTING_CONTACT_LIST_PERIOD = 10;
	var MYSELF_DISPLAY = 'I said';
	
	
	//Variables
	var contactList = null;
	
	function Contact(userName, displayName, status, isOnline)
	{
		this.userName = userName;
		this.displayName = displayName;
		this.status = status;
		this.isOnline = isOnline;
	}
	
	
	function openChatDialog(strContactId, strDisplayName)
	{
		var strDialogId = PREFIX_CHAT_DIALOG_ID + strContactId;
		createChatDialog(strContactId, strDisplayName);
		$('#' + strDialogId).dialog('open');
		$('#scrollbarChatDialog_' + strContactId).tinyscrollbar();
	}

	function createChatDialog(strContactId, strDisplayName)
	{
		var strDialogId = PREFIX_CHAT_DIALOG_ID + strContactId;;
		if ($('#' + strDialogId).length > 0)
		{
			var scrollbar = $('#' + PREFIX_CHAT_CONTENT_SCROLLBAR_ID + strContactId);
			scrollbar.tinyscrollbar_update('bottom'); 
		}
		else
		{
			var strInnerHtml = prepareChatDialogHtml(strContactId, strDisplayName);
			$('#divChatContentPanel').append(strInnerHtml);

			$('#' + strDialogId).dialog({
				autoOpen: false,
				height: 221,
				width: 214,
				modal: false,
				resizable: false,
			});
			$('#' + PREFIX_CHAT_CONTENT_SCROLLBAR_ID + strContactId).tinyscrollbar();			
		}	
	}
	
	function prepareChatDialogHtml(strContactId, strDisplayName)
	{
		var strChatDialogId = PREFIX_CHAT_DIALOG_ID + strContactId;
		var strChatContentId = PREFIX_CHAT_CONTENT_ID + strContactId;
		var strTextboxMessageId = PREFIX_CHAT_TEXT_BOX_MESSAGE_ID + strContactId;
		var strScrollbarId = PREFIX_CHAT_CONTENT_SCROLLBAR_ID + strContactId;
		
		var html = $('<div id="' + strChatDialogId + '" title="' + strDisplayName + '" style="padding: 5px 2px 0px 1px; font-family:\'arial\', \'tahoma\', \'segoe\', \'Helvetica Condensed\'; font-size: 12px;"></div>');
		html.append('<div class="divChatContent"><div id="' + strScrollbarId + '" class="scrollbarChatDialog"><div class="scrollbarChatDialog scrollbar"><div class="scrollbarChatDialog track"><div class="scrollbarChatDialog thumb"></div></div></div><div class="scrollbarChatDialog viewport"><div id="' + strChatContentId + '" class="scrollbarChatDialog overview"></div></div></div></div>');
		html.append('<div style="height: 22px; overflow: hidden; margin-top: 4px;"><input id="' + strTextboxMessageId + '" type="text" name="txtMsg" style="width: 100%;" onkeydown="textboxMessageKeyDown(event, this);"/></div>');
		return html;
	}

	
	function textboxMessageKeyDown(evt, textbox)
	{
		var theEvent = evt || window.event;		
		var key = theEvent.keyCode || theEvent.which;
		var isEnterKey = checkForEnterKeyPress(key);
		if (isEnterKey)
		{
			var strMsg = textbox.value.trim();
			if (strMsg != '')
			{
				textbox.value = '';
				var str = $(textbox).attr('id');
				var strContact = str.substring(PREFIX_CHAT_TEXT_BOX_MESSAGE_ID.length);
				var chatContent = $('#' + PREFIX_CHAT_CONTENT_ID + strContact);
				var needToShowContactName = false;
				if (chatContent.children().length < 1
						|| chatContent.hasClass(DUMMY_CLASS_IAM_TYPING) == false) {
					needToShowContactName = true;
				}
				
				var nameToDisplay = "";
				if (needToShowContactName == true) {
					nameToDisplay = MYSELF_DISPLAY + ":&nbsp;";
				}	
				var strTagToAppended = '<div'+ (needToShowContactName == false ? " style='padding-left: 8px; padding-top: 5px;'" : " style='padding-top: 5px;'") + '><span class="mySentMessage">' + nameToDisplay + '</span>' + strMsg + '</div>';
				chatContent.addClass(DUMMY_CLASS_IAM_TYPING);
				chatContent.append(strTagToAppended);

				sendMessage(userName, strContact, strMsg);

				var oScrollbar = $('#' + PREFIX_CHAT_CONTENT_SCROLLBAR_ID + strContact);
				oScrollbar.tinyscrollbar_update('bottom'); 
			}
		}
// 		key = String.fromCharCode(key);
// 		var regex = /[0-9]/;
// 		if(!regex.test(key) && !isCtrlKey)// isCtrlKey: is used for checking '+'
// 		{
// 			theEvent.returnValue = false;
// 			if(theEvent.preventDefault) 
// 			{
// 				theEvent.preventDefault();
// 			}
// 		}
	}
	
	//This function will be fired after finish getting contact list
	function checkForNewChatMessage() {
		setTimeout(function () {
			//alert('check for new mail mesage!');
			retrieveMessage();
			checkForNewChatMessage();
		}, REFRESHING_CHATTING_PERIOD * 1000);
	}
	
	//This function will be fired after finish 
	function refreshContactList() {
		setTimeout(function () {
			getOnlineContact();
			refreshContactList();
		}, REFRESHING_CHATTING_CONTACT_LIST_PERIOD * 1000);
	}
	
	function displayContactList()
	{
		$("#contactlist").html("");
		contactList.each(function(i, item){
			  var userName = $("UserName", item).text();
			  var displayName = $("DisplayName", item).text();
			  var status = $("Status", item).text();
			  var online = $(item).attr("IsOnline");
			  //alert(userName + ": isOnline = ");
			  addContactToList(userName, displayName, status, online == "true" ? true : false);
		  });
	}
	
	function addContactToList(userName, displayName, status, isOnline)
	{
		var contactList = $("#contactlist");
		var count = $("tr", contactList).length;
		var rowStyleClass = (count % 2 == 0) ? "trContactListAlternative" : "trContactList";
		var contactRow = $("<tr class='" + rowStyleClass + "' />");

		contactRow.attr("id", "contact_" + userName);
		contactRow.click(function(){
			openChatDialog(userName, displayName);
		});

		var icon = $("<td class='tdContactIcon' />");
		icon.addClass(isOnline == true ? " tdContatctIconOnline" : "tdContatctIconOffline");

		var contactNameAndStatus = $("<td ><span class='tdContactName'>" + displayName + "</span><span  class='tdContactStatus'>" + status + "</span></td>");

		contactRow.append(icon);
		contactRow.append(contactNameAndStatus);

		contactList.append(contactRow);
	}

	function sendMessage(from, to, msg)
	{
		$.ajax({
			  url: "Chat",
			  type: "POST",
			  data: {
				  		action: "send", 
				  		sender: from, 
				  		receiver: to, 
				  		message: msg
			  		},//"action=send&sender=vanpham&receiver=khaitran&message=hello",
			  success: function(data) {
				  
			  }
		});
		
	}
	
	function retrieveMessage()
	{
		$.ajax({
			  url: "Chat",
			  type: "POST",
			  data: {
				  action: "retrieve",
				  receiver: userName 
			  },
			  success: function(data) {
				  
				  //Group received messages by sender
				  var senders = new Array();
				  var items = $("MessageItem", data);
				  var i = 0;
				  var senderCount = 0;
				  for (i = 0; i < items.length; i++)
				  {
					  var item = items[i];
					  var obj;
					  var senderName = $("Sender", item).text();
					  var message =  $("Message", item).text();
					  var sentDate =  $("SentDate", item).text();
					  var idx = checkForExistedSender(senders, senderName);
					  if (idx > -1)
					  {
						  obj = senders[idx];
					  }
					  else
					  {
						  obj = new Object();
						  obj.message = new Array();
						  obj.sentDate = new Array();
						  obj.sender = senderName;
						  senders.push(obj);
						  senderCount++;
					  }
					  
					  var msgCount = obj.message.length;
					  obj.message[msgCount] = message;
					  obj.sentDate[msgCount] = sentDate;
				  }
				  
				  //foreach sender, sort message by sent date and show them
				  for (i = 0; i < senders.length; i++)
				  {
					  sortByDate(senders[i]);
					  openChatDialog(senders[i].sender, senders[i].sender);
					  showRetrievedMessages(senders[i]);
				  }
				  	
			  }//end of success	
		});//End of ajax
		
	}
	
	function getOnlineContact()
	{
		$.ajax({
				url: "Chat",
				type: "POST",
				data: {
				action: "getOnlineList",
				receiver: userName 
			},
			success: function(data) {
				onlineList = $("ContactItem", data);
				//mark all as offline
				contactList.attr("IsOnline", "false");
				onlineList.each(function(i, item){
					
					var onUserName = $("UserName", item).text();
					var onStatus = $("Status", item).text();
					contactList.each(function(j, contact){
						var userName = $("UserName", contact).text();
						//alert(userName + " vs " + onUserName);
						if (userName.toLowerCase() == onUserName.toLowerCase())
						{
							$(contact).attr("IsOnline", "true");
							$(contact).attr("Status", onStatus);
							//alert($(contact).attr("IsOnline"));
						}
					});
				});
				displayContactList();
			}//end of success	
		});//End of ajax
		
	}
	
	function getContactList()
	{
		$.ajax({
			  url: "Chat",
			  type: "POST",
			  data: {
				  action: "getContactList"
				  //receiver: userName 
			  },
			  success: function(data) {
				  contactList = $("ContactItem", data);
				  contactList.each(function(i, item){
					  $(item).attr("IsOnline", "false");
				  });
				  
				  refreshContactList();
				  displayContactList();
				  checkForNewChatMessage();
			  }//end of success	
		});//End of ajax
		
	}
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// Helpers
	
	
	///
	/// senders: array of Sender{Message, SentDate, SenderName}
	///
	function checkForExistedSender(senders, name)
	{
		var i = 0;
		for (i = 0; i < senders.length; i++)
		{
			if (senders[i].sender != undefined && senders[i].sender.toLowerCase() == name.toLowerCase())
			{
				return i;
			}
		}
		return -1;
	}
	
	function sortByDate(sender)
	{
		if (sender == undefined)
			return;
		var length = sender.sentDate.length;
		var i;
		for (i = 1; i < length; i++)
		{
			var j;
			for (j = 0; j < length - i; j++)
			{
				if (sender.sentDate[j] > sender.sentDate[j+1])
				{
					//swap date
					var temp = sender.sentDate[j];
					sender.sentDate[j] = sender.sentDate[j+1];
					sender.sentDate[j+1] = temp;
					
					//swap message
					var temp2 = sender.message[j];
					sender.message[j] = sender.message[j+1];
					sender.message[j+1] = temp2;
				}
			}
		}
	}
	
	function showRetrievedMessages(from)
	{
		var count = from.message.length;
		for (var i = 0; i < count; i++)
		{
			showMessage(from.sender, from.message[i], from.sentDate[i], false);
		}
	}

	function showMessage(senderName, message, sentDate, isMySentMsg)
	{
		//TODO: show more information such as time
		var chatContent = $('#' + PREFIX_CHAT_CONTENT_ID + senderName);
		var needToShowContactName = false;
		if (chatContent.children().length < 1
				|| (chatContent.hasClass(DUMMY_CLASS_IAM_TYPING) == true && isMySentMsg == false) 
				|| (chatContent.hasClass(DUMMY_CLASS_IAM_TYPING) == false && isMySentMsg == true)) {
			needToShowContactName = true;
		}
		
		//alert(needToShowContactName);
		var classStyle = (isMySentMsg == true ? "mySentMessage" : "myReceivedMessage");
		var nameToDisplay = (isMySentMsg == true ? MYSELF_DISPLAY : senderName) + ": &nbsp;";
		
		var tagToAppended = '<div'+ (needToShowContactName == false ? " style='padding-left:8px; padding-top: 5px;'" : " style='padding-top: 5px;'") + '><span class="' + classStyle + '">' + (needToShowContactName == true ? nameToDisplay : "") + '</span>' + message + '</div>';
		
		if (isMySentMsg == true){
			chatContent.addClass(DUMMY_CLASS_IAM_TYPING);
		}
		else {
			chatContent.removeClass(DUMMY_CLASS_IAM_TYPING);
		}
			
		
		chatContent.append(tagToAppended);

		var oScrollbar = $('#' + PREFIX_CHAT_CONTENT_SCROLLBAR_ID + senderName);
		oScrollbar.tinyscrollbar_update('bottom'); 
	}
	
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	